// (C) 2021 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module avmm_mux_1to2_with_err_report #(
    parameter SLV1_ADDR_LOW  = 32'h0000,
    parameter SLV1_ADDR_High = 32'h00FF,
    parameter SLV2_ADDR_LOW  = 32'h0100,
    parameter SLV2_ADDR_High = 32'h01FF
)(
    input             clk,           
    input             rst_n,
    //AVMM_Single_Master
    input      [31:0] mst_address,
    input             mst_write,
    input      [31:0] mst_writedata,          
    input             mst_read,     
    output reg [31:0] mst_readdata,      
    output            mst_readdatavalid, 
    output            mst_waitrequest,           
    input      [ 3:0] mst_byteenable,
    output            invalid_access,	 
    //AVMM_Slave_1
    output reg [31:0] slv1_address,
    output reg        slv1_write,
    output     [31:0] slv1_writedata,          
    output reg        slv1_read,       
    input      [31:0] slv1_readdata,      
    input             slv1_readdatavalid, 
    input             slv1_waitrequest,            
    output     [ 3:0] slv1_byteenable,
	 input             invalid_access_slv1,
    //AVMM_Slave_2
    output reg [31:0] slv2_address,
    output reg        slv2_write,
    output     [31:0] slv2_writedata,          
    output reg        slv2_read,       
    input      [31:0] slv2_readdata,      
    input             slv2_readdatavalid, 
    input             slv2_waitrequest,            
    output     [ 3:0] slv2_byteenable,
	 input             invalid_access_slv2 
);

reg    invalid_access_rsv;


//pass input writedata & byteenable signals from master port to each slave ports directly.
assign slv1_writedata  = mst_writedata;
assign slv1_byteenable = 4'hF;

assign slv2_writedata  = mst_writedata;
assign slv2_byteenable = 4'hF;

assign invalid_access = invalid_access_slv1 || invalid_access_slv2 || invalid_access_rsv;


reg [1:0] cs;
reg [1:0] cs_latch;

always @ (*) begin
    if( mst_address >= SLV1_ADDR_LOW && mst_address <= SLV1_ADDR_High ) begin
        cs                    = 2'b01;
		  invalid_access_rsv    = 1'b0;
    end else if ( mst_address >= SLV2_ADDR_LOW && mst_address <= SLV2_ADDR_High ) begin
        cs                    = 2'b10;
		  invalid_access_rsv    = 1'b0;  
    end else begin
        cs                    = 2'b00;
		  invalid_access_rsv    = 1'b1;
    end  
end

always @ ( posedge clk) begin
    if ( !rst_n ) begin
        cs_latch <= 2'b0;
    end else begin
        if ( mst_read ) begin
            cs_latch <= cs;
        end else begin
            cs_latch <= cs_latch;
        end
    end
end

//pass slave readdata to mast according to address range.
always @ (*) begin
    case ( cs_latch )
        2'b1    : mst_readdata <= slv1_readdata;
        2'b10   : mst_readdata <= slv2_readdata;
        default : mst_readdata <= 'b0;
    endcase
end 

//pass relative addr from mst to slv
always @ (*) begin
    case ( cs )
        2'b01   : begin
                     slv1_address <= mst_address - SLV1_ADDR_LOW; // Use Relative addr to selected slave device
                     slv2_address <= 'b0;
                  end
        2'b10  : begin
                     slv2_address <= mst_address - SLV2_ADDR_LOW; // Use Relative addr to selected slave device
                     slv1_address <= 'b0;
                  end                  
        default : begin
	                 slv1_address <= 'b0;
                     slv2_address <= 'b0;
				  end
    endcase
end 

//pass mst_write to slave according to cs
always @ (*) begin
    case ( cs )
        2'b01   : begin
                     slv1_write <= mst_write;
                     slv2_write <= 'b0;
                  end
        2'b10  : begin
                     slv2_write <= mst_write;
                     slv1_write <= 'b0;
                  end                   
        default : begin
	                 slv1_write <= 'b0;
                     slv2_write <= 'b0;
				  end
    endcase
end 

//pass mst_read to slave according to cs
always @ (*) begin
    case ( cs )
        2'b01   : begin
                     slv1_read <= mst_read;
                     slv2_read <= 'b0;
                  end
        2'b10  : begin
                     slv2_read <= mst_read;
                     slv1_read <= 'b0;
                  end                  
        default : begin
	                 slv1_read <= 'b0;
                     slv2_read <= 'b0;
				  end
    endcase
end 

assign mst_waitrequest   = slv1_waitrequest || slv2_waitrequest;
assign mst_readdatavalid = slv1_readdatavalid || slv2_readdatavalid;

endmodule
